﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using ArtMath.Core.Data;
using ArtMath.Data;
using ArtMath.Setting;
using ArtMath.Attribute;
using ArtMath.Resource;
using ArtMath.CommonType;
using ArtMath.Component.Converter;

namespace ArtMath.Component
{
    [Serializable]
    public abstract class ClosedShapeBase : LineBase
    {
        ColorX fillColor, linear1, linear2;
        PropertyDisplayer sDisplayer, cDisplayer;
        FillStyle fillStyle = Settings.Instance.ClosedShapeFillStyle;
        AngleStringX linearAngle;
        protected RectangleD FillRegion;
        public ClosedShapeBase(SketchPad pad, string name, ToolTypeName toolType, bool addToList = true) : base(pad, name, toolType, addToList)
        {
            fillColor = new ColorX(Pad, Settings.Instance.ClosedShapeFillColor);
            linear1 = new ColorX(Pad, Settings.Instance.LinearGradientStartColor);
            linear2 = new ColorX(Pad, Settings.Instance.LinearGradientEndColor);
            LinearGradientAngle = new AngleStringX(Pad, Settings.Instance.ClosedShapeLinearAngle);
            CDisplayer = new PropertyDisplayer(this, "Circumference");
            SDisplayer = new PropertyDisplayer(this, "Area");
        }

        [MultilingualCategory("Parameter"), MultilingualDisplayName("Circumference")]
        public double Circumference { get; protected set; }
        //[Browsable(false)]
        //public virtual double NewCircumference
        //{
        //    get { return 0; }
        //}
        [MultilingualCategory(null, "Sketchpad", "Display"), MultilingualDisplayName(null, "Circumference", "Displayer")]
        public PropertyDisplayer CDisplayer
        {
            get { return cDisplayer; }
            set { cDisplayer = value; }
        }
        [MultilingualCategory("Parameter"), MultilingualDisplayName("Area")]
        public double Area { get; protected set; }
        [MultilingualCategory(null, "Sketchpad", "Display"), MultilingualDisplayName(null, "Area", "Displayer")]
        public PropertyDisplayer SDisplayer
        {
            get { return sDisplayer; }
            set { sDisplayer = value; }
        }
        [MultilingualCategory("Appearance"), DefaultValue(typeof(FillStyle), "SolidColor"), MultilingualDisplayName("FillStyle"), TypeConverter(typeof(FillStyleConverter))]
        public FillStyle FillStyle
        {
            get { return fillStyle; }
            set
            {
                fillStyle = value;
                Pad.Canvas.Invalidate();
            }
        }
        [MultilingualCategory("Appearance"), DefaultValue(typeof(Color), "Transparent"), MultilingualDisplayName("SolidFillColor")]
        public Color SolidFillColor
        {
            get { return fillColor.Color; }
            set { fillColor.Color = value; }
        }
        [MultilingualCategory("Appearance"), DefaultValue(typeof(Color), "LightBlue"), MultilingualDisplayName("LinearGradientStartColor")]
        public Color LinearGradientStartColor
        {
            get { return linear1.Color; }
            set { linear1.Color = value; }
        }
        [MultilingualCategory("Appearance"), DefaultValue(typeof(Color), "LightGreen"), MultilingualDisplayName("LinearGradientEndColor")]
        public Color LinearGradientEndColor
        {
            get { return linear2.Color; }
            set { linear2.Color = value; }
        }
        [MultilingualCategory("Appearance"), DefaultValue(typeof(AngleStringX), "0"), MultilingualDisplayName("LinearGradientAngle")]
        public AngleStringX LinearGradientAngle
        {
            get { return linearAngle; }
            set { linearAngle = value; }
        }
        public override void ComponentBuilding(Base component)
        {
            AppendStatus($"{Resources.CommaSeparate}{Resources.Translate("Circumference")} = {Circumference}{Resources.CommaSeparate}{Resources.Translate("Area")} = {Area}", true);
            base.ComponentBuilding(component);
        }
        public override void RefreshPropertyDisplayersLocation()
        {
            CDisplayer.RefreshLocation();
            SDisplayer.RefreshLocation();
            base.RefreshPropertyDisplayersLocation();
        }
        public override void RefreshPropertyDisplayersText()
        {
            CDisplayer.RefreshText();
            SDisplayer.RefreshText();
            base.RefreshPropertyDisplayersText();
        }
        public override void PaintProperties(Graphics gra)
        {
            if (ObjectState == ObjectState.Normal && Visible)
            {
                CDisplayer.Paint(gra);
                SDisplayer.Paint(gra);
            }
            base.PaintProperties(gra);
        }
        [Browsable(false)]
        protected Brush FillBrush
        {
            get
            {
                switch (FillStyle)
                {
                    case FillStyle.SolidColor:
                        return new SolidBrush(StyleState_ == StyleState.Hover || Selected && Pad.UseReversedColor ? fillColor.ReversedColor : fillColor.Color);
                    case FillStyle.LinearGradientColor:
                        if (FillRegion.IsDrawable)
                        {
                            RectangleF rect = new RectangleF(FillRegion.Location.ToPointF(), FillRegion.Size.ToSizeF());
                            return new LinearGradientBrush(rect, StyleState_ == StyleState.Hover || Selected && Pad.UseReversedColor ? linear1.ReversedColor : linear1.Color,
                                StyleState_ == StyleState.Hover || Selected && Pad.UseReversedColor ? linear2.ReversedColor : linear2.Color, LinearGradientAngle.FloatValue);
                        }
                        break;
                }
                return null;
            }
        }
        public override PropertyDisplayer[] PropertyDisplayersCheckNearBy(PointD Plocation)
        {
            List<PropertyDisplayer> res = new List<PropertyDisplayer>(base.PropertyDisplayersCheckNearBy(Plocation));
            if (CDisplayer.InRegion(Plocation))
            {
                res.Add(CDisplayer);
            }
            if (SDisplayer.InRegion(Plocation))
            {
                res.Add(SDisplayer);
            }
            return res.ToArray();
        }
    }
}
